package com.bugs.activity;

import cn.hutool.core.collection.CollectionUtil;
import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
 * 流程变量 测试类
 */
public class VariableDemo {

    /**
     * 单文件上传部署逻辑
     */
    @Test
    public void addTable(){
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
        Deployment demo1 = repositoryService.createDeployment()
                .addClasspathResource("bpmn/demo02.bpmn") // 添加流程图
                .addClasspathResource("bpmn/demo02.png") // 对应的流程图片 支持 png|jpg|gif|svg
                .name("内部与外部申请审批流程")
                .deploy();
        System.out.println("流程部署id===》"+demo1.getId());
        System.out.println("流程部署name===》"+demo1.getName());
    }


    /**
     * 启动实例
     * 这里针对条件  分别启动两个流程实例
     */
    @Test
    public void startProcess(){
        // 获取流程引擎
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取 runtime 服务
        RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();
        // 指定哪个模板
        String tempKey = "demo02";

        // 流程变量  可以是对象 也可以是单个的类型变量 比如 字符串
        HashMap<String, Object> paramMap = new HashMap<>();

        //paramMap.put("amt",10000); // 流程1
        // 指定责任人
        //paramMap.put("assignee0","worker"); // 流程1

        paramMap.put("amt",10000001); // 流程2
        paramMap.put("assignee0","worker1"); // 流程2

        // 启动流程实例
        runtimeService.startProcessInstanceByKey(tempKey,paramMap);
    }

    /**
     * 查询流程实例信息
     */
    @Test
    public void queryTask(){
        // 执行已部署的流程模板名称
        String tempKey = "demo02";
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = defaultProcessEngine.getTaskService();

        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey(tempKey) // 指定哪个流程图模板
                .list();
        if(!CollectionUtil.isEmpty(list)){
            list.forEach(x->{
                System.out.println("流程实例 id "+x.getProcessInstanceId());
                System.out.println("任务 id "+x.getId());
                System.out.println("任务负责人 "+x.getAssignee());
                System.out.println("任务名称 "+x.getName());
                System.out.println("===========================================");
            });
        }
    }

    /**
     * 工作流的节点与状态的扭转
     * 这里有2个流程  分别对对应的任务 id 进行流程的推进
     */
    @Test
    public void completTask(){
        String tempKey = "demo02";
        // 负责人 信息
        //String assignee = "worker"; // 流程1
        String assignee = "worker1"; // 流程2
        // 获取数据库的连接信息
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = defaultProcessEngine.getTaskService();

        Task task = taskService.createTaskQuery().processDefinitionKey(tempKey).taskAssignee(assignee).singleResult();
        if(Objects.nonNull(task)){
            System.out.println("========= 任务 "+ task.getId()+" 进行流程推进 ==========");
            taskService.complete(task.getId());
        }

    }

    /**
     *  部门经理审批任务  实现任务流程节点的推进
     * 工作流的节点与状态的扭转
     * 这里有2个流程  分别对对应的任务 id 进行流程的推进
     */
    @Test
    public void completTask2(){
        String tempKey = "demo02";
        // 负责人 信息
        String assignee = "manager";
        // 获取数据库的连接信息
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = defaultProcessEngine.getTaskService();

        List<Task> tasks = taskService.createTaskQuery().processDefinitionKey(tempKey).taskAssignee(assignee).list();
        if(!CollectionUtil.isEmpty(tasks)){
            tasks.forEach(task->{
                taskService.complete(task.getId());
            });
        }

    }




    /**
     * 查询流程定义 的一些内容
     */
    @Test
    public void queryProcessDefinition(){
        // 获取数据库的连接信息
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();

        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();

        // 指定需要查询哪个流程模板信息
        String flowId = "demo02";
        List<ProcessDefinition> list = processDefinitionQuery
                .processDefinitionKey(flowId) // 指定是哪个流程模板
                .orderByProcessDefinitionVersion() // 排序字段
                .desc()
                .list();
        if(!CollectionUtil.isEmpty(list)){
            list.forEach(process->{
                System.out.println("流程定义 id "+process.getId());
                System.out.println("流程定义 name "+process.getName());
                System.out.println("流程定义 key "+process.getKey());
                System.out.println("流程定义 version "+process.getVersion());
                System.out.println("流程部署 id "+process.getDeploymentId());
                System.out.println("=============================");
            });
        }
    }

    /**
     * 删除 已部署 的流程实例。
     * 注意：如果当前流程实例并未执行完成，进行删除时会出现报错。
     *
     * 需要根据  RepositoryService 去查询   DeploymentId
     */
    @Test
    public void deleteDeployment(){
        // 流程部署id
        String deployMentId = "25001"; // 15001
        // 获取数据库的连接信息
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
        // 当该已部署的流程，存在流程中的实例时，执行当前流程会报错！
        //repositoryService.deleteDeployment(deployMentId);
        // 如果需要进行强制删除  则可以采取下列的方式进行
        repositoryService.deleteDeployment(deployMentId,true);
    }


}
